// Enigma wheel I
// No. ABCDEFGHIJKLMNOPQRSTUVWXYZ
// I EKMFLGDQVZNTOWYHXUSPAIBRCJYQ
module Rotar8(clk,Din_left,Dout_left,rst,acc);
`define DANGER 6'd0
`define A 6'd1
`define  B 6'd2
`define  C 6'd3
`define  D 6'd4
`define  E 6'd5
`define  F 6'd6
`define  G 6'd7
`define  H 6'd8
`define  I 6'd9
`define  J 6'd10
`define  K 6'd11
`define  L 6'd12
`define  M 6'd13
`define  N 6'd14
`define  O 6'd15
`define  P 6'd16
`define  Q 6'd17
`define  R 6'd18
`define  S 6'd19
`define  T 6'd20
`define  U 6'd21
`define  V 6'd22
`define  W 6'd23
`define  X 6'd24
`define  Y 6'd25
`define  Z 6'd26
wire[5:0] LA = `A;
wire[5:0] LB = `B;
wire[5:0] LC = `C;
wire[5:0] LD = `D;
wire[5:0] LE = `E;
wire[5:0] LF = `F;
wire[5:0] LG = `G;
wire[5:0] LH = `H;
wire[5:0] LI = `I;
wire[5:0] LJ = `J;
wire[5:0] LK = `K;
wire[5:0] LL = `L;
wire[5:0] LM = `M;
wire[5:0] LN = `N;
wire[5:0] LO = `O;
wire[5:0] LP = `P;
wire[5:0] LQ = `Q;
wire[5:0] LR = `R;
wire[5:0] LS = `S;
wire[5:0] LT = `T;
wire[5:0] LU = `U;
wire[5:0] LV = `V;
wire[5:0] LW = `W;
wire[5:0] LX = `X;
wire[5:0] LY = `Y;
wire[5:0] LZ = `Z;
wire[5:0] danger = `DANGER;
input clk,rst,acc;
wire clk,rst,acc;
reg [5:0]Din_right;
input [5:0] Din_left;
output [5:0] Dout_left;
reg[5:0]Dout_left;
reg [5:0] Dout_right;
reg [5:0] position;
reg [5:0] ix_right;
reg[5:0] val_right;
reg[5:0] val_left;
reg[5:0] wrapped_val_right;
reg[5:0] wrapped_val_left;
reg[5:0] ix_left;
reg[5:0] val;
reg [2:0]S;
reg [2:0]NS;

parameter START = 3'd0, WAIT = 3'd1, REFLECT = 3'd2, CODEIN = 3'd3, CODEOUT = 3'd4, COUNT = 3'd5, CASEWRAP = 3'd6,DANGER = 3'd7;

always@(posedge clk or negedge rst)
begin
	if(rst==1'b0)
		S<=START;
	else
		S<=NS;
end

always@(*)
begin
	case(S)
		START: if(Din_left==danger)
			NS=START;
		else
			NS=WAIT;
		WAIT:if(acc==1'b1)
		begin
			NS=CODEIN;
		end
		else
		begin
			NS=WAIT;
		end
		CODEIN:if(acc==1'b0)
		begin
			NS=REFLECT;
		end
		else
		begin
			NS=CODEIN;
		end
		REFLECT: NS=CODEOUT;
		CODEOUT: NS=COUNT;
		COUNT: NS=CASEWRAP;
		CASEWRAP:NS=WAIT;
		default: NS=DANGER;
	endcase
end

always @(posedge clk or negedge rst)
begin
	case(S)
	START:
	begin
		position = 5'b00000;
		wrapped_val_right<=danger;
	end
	CODEIN:
	begin
		if( Din_left<position )
			ix_left <= (Din_left-(position+26));
		else
			ix_left <= (Din_left-position);
		case( ix_left )
			LA: val_right <= LE;
			LB: val_right <= LK;
			LC: val_right <= LM;
			LD: val_right <= LF;
			LE: val_right <= LL;
			LF: val_right <= LG;
			LG: val_right <= LD;
			LH: val_right <= LQ;
			LI: val_right <= LV;
			LJ: val_right <= LZ;
			LK: val_right <= LN;
			LL: val_right <= LT;
			LM: val_right <= LO;
			LN: val_right <= LW;
			LO: val_right <= LY;
			LP: val_right <= LH;
			LQ: val_right <= LX;
			LR: val_right <= LU;
			LS: val_right <= LS;
			LT: val_right <= LP;
			LU: val_right <= LA;
			LV: val_right <= LI;
			LW: val_right <= LB;
			LX: val_right <= LR;
			LY: val_right <= LC;
			LZ: val_right <= LJ;
			LA+26: val_right <= LE;
			LB+26: val_right <= LK;
			LC+26: val_right <= LM;
			LD+26: val_right <= LF;
			LE+26: val_right <= LL;
			LF+26: val_right <= LG;
			LG+26: val_right <= LD;
			LH+26: val_right <= LQ;
			LI+26: val_right <= LV;
			LJ+26: val_right <= LZ;
			LK+26: val_right <= LN;
			LL+26: val_right <= LT;
			LM+26: val_right <= LO;
			LN+26: val_right <= LW;
			LO+26: val_right <= LY;
			LP+26: val_right <= LH;
			LQ+26: val_right <= LX;
			LR+26: val_right <= LU;
			LS+26: val_right <= LS;
			LT+26: val_right <= LP;
			LU+26: val_right <= LA;
			LV+26: val_right <= LI;
			LW+26: val_right <= LB;
			LX+26: val_right <= LR;
			LY+26: val_right <= LC;
			LZ+26: val_right <= LJ;
			default: val_right <= danger;
		endcase
		wrapped_val_right <= (val_right+position);
		end
		REFLECT: 
		begin
			case(wrapped_val_right)
				LA: val <= LY;
				LB: val <= LR;
				LC: val <= LU;
				LD: val <= LH;
				LE: val <= LQ;
				LF: val <= LS;
				LG: val <= LL;
				LH: val <= LD;
				LI: val <= LP;
				LJ: val <= LX;
				LK: val <= LN;
				LL: val <= LG;
				LM: val <= LO;
				LN: val <= LK;
				LO: val <= LM;
				LP: val <= LI;
				LQ: val <= LE;
				LR: val <= LB;
				LS: val <= LF;
				LT: val <= LZ;
				LU: val <= LC;
				LV: val <= LW;
				LW: val <= LV;
				LX: val <= LJ;
				LY: val <= LA;
				LZ: val <= LT;
				LA+26: val <= LY;
				LB+26: val <= LR;
				LC+26: val <= LU;
				LD+26: val <= LH;
				LE+26: val <= LQ;
				LF+26: val <= LS;
				LG+26: val <= LL;
				LH+26: val <= LD;
				LI+26: val <= LP;
				LJ+26: val <= LX;
				LK+26: val <= LN;
				LL+26: val <= LG;
				LM+26: val <= LO;
				LN+26: val <= LK;
				LO+26: val <= LM;
				LP+26: val <= LI;
				LQ+26: val <= LE;
				LR+26: val <= LB;
				LS+26: val <= LF;
				LT+26: val <= LZ;
				LU+26: val <= LC;
				LV+26: val <= LW;
				LW+26: val <= LV;
				LX+26: val <= LJ;
				LY+26: val <= LA;
				LZ+26: val <= LT;
				default: val <= danger;
			endcase
			Din_right = val;
		end
		CODEOUT:
		begin
			if( Din_right<position )
				ix_right <= (Din_right-(position+26));
			else
				ix_right <= (Din_right-position);
			case( ix_right )
				LE: val_left <= LA;
				LK: val_left <= LB;
				LM: val_left <= LC;
				LF: val_left <= LD;
				LL: val_left <= LE;
				LG: val_left <= LF;
				LD: val_left <= LG;
				LQ: val_left <= LH;
				LV: val_left <= LI;
				LZ: val_left <= LJ;
				LN: val_left <= LK;
				LT: val_left <= LL;
				LO: val_left <= LM;
				LW: val_left <= LN;
				LY: val_left <= LO;
				LH: val_left <= LP;
				LX: val_left <= LQ;
				LU: val_left <= LR;
				LS: val_left <= LS;
				LP: val_left <= LT;
				LA: val_left <= LU;
				LI: val_left <= LV;
				LB: val_left <= LW;
				LR: val_left <= LX;
				LC: val_left <= LY;
				LJ: val_left <= LZ;
				LE+26: val_left <= LA;
				LK+26: val_left <= LB;
				LM+26: val_left <= LC;
				LF+26: val_left <= LD;
				LL+26: val_left <= LE;
				LG+26: val_left <= LF;
				LD+26: val_left <= LG;
				LQ+26: val_left <= LH;
				LV+26: val_left <= LI;
				LZ+26: val_left <= LJ;
				LN+26: val_left <= LK;
				LT+26: val_left <= LL;
				LO+26: val_left <= LM;
				LW+26: val_left <= LN;
				LY+26: val_left <= LO;
				LH+26: val_left <= LP;
				LX+26: val_left <= LQ;
				LU+26: val_left <= LR;
				LS+26: val_left <= LS;
				LP+26: val_left <= LT;
				LA+26: val_left <= LU;
				LI+26: val_left <= LV;
				LB+26: val_left <= LW;
				LR+26: val_left <= LX;
				LC+26: val_left <= LY;
				LJ+26: val_left <= LZ;
				default: val_left <= danger;
			endcase
		wrapped_val_left <= val_left+position;
	end
	COUNT:
	begin
		if(position >25)
			position <= position-25;
		else
			position <= position + 1;
	end
	CASEWRAP:
	begin
	if( wrapped_val_left>=26 )
		Dout_left <= wrapped_val_left-26;
	else
		Dout_left <= wrapped_val_left;
	end
endcase
end
endmodule
